﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
//using SYNANLib;

namespace OffLineFilter
{
    public class Filter
    {
        private Statistics statistics;
        public Dictionary dictionary { get; set; }
        public string FileName { get; set; }
        public string SolutionTreeFileName { get; set; }
        public int MaxIdfPercent { get; set; }

        public Filter(String fileName, Dictionary dictionary, String solutionTree, int maxIdfPercent)
        {
            this.dictionary = dictionary;
            FileName = fileName;
            SolutionTreeFileName = solutionTree;
            MaxIdfPercent = maxIdfPercent;
        }

        public IdfStageResult IdfStage()
        {
            FileNormalizer normalizer = new FileNormalizer(FileName);
            IdfFilter filter = new IdfFilter(dictionary, MaxIdfPercent);

            return new IdfStageResult
            {
                Result = filter.MakeCheck(normalizer.Normalize()),
                Defects = filter.Defects
            }; 
        }

        public StatisticsStageResult StatisticsStage()
        {
            FileCompressor compressor = new FileCompressor(FileName);
            statistics = new Statistics(FileName, dictionary);
            statistics.GetStatistics();

            double gzipRate = compressor.Compress(CompressingType.Gzip);
            double bz2Rate = compressor.Compress(CompressingType.Bz2);

            double[] d = new[]
            {
                gzipRate,
                bz2Rate,
                statistics.AdverbVariance,
                statistics.InterjectionVariance,
                statistics.ParticleVariance,
                statistics.PretextVariance,
                statistics.AdverbPercent,
                statistics.PronominalAdjectiveVariance,
                statistics.PronominalNounVariance,
                statistics.PronominalNounPercent,
                statistics.VerbPercent,
                statistics.VerbVarianve,
                statistics.AverageNonstopSentenceLength,
                statistics.AverageSentenceLength,
                statistics.PretextPercent,
                statistics.NounVariance,
                statistics.IntermediatePunctuationPercent,
                statistics.EndPunctuationPercent,
                statistics.NounPercent
            };

            Dictionary<int, double> dict = new Dictionary<int, double>();
            for (int i = 0; i < d.Length; i++)
                dict.Add(i + 1, d[i]);

            SolutionTreeResolver resolver = new SolutionTreeResolver(SolutionTreeFileName, dict);
            resolver.Parse();

            return new StatisticsStageResult
            {
                GzipRate = gzipRate,
                Bz2Rate = bz2Rate,
                Variances = statistics.Variances,
                Percents = statistics.Percents,
                Solution = resolver.Solution + "(" + resolver.LeafId + ")",
                AvgLength = statistics.AverageSentenceLength,
                AvgLengthWithoutStop = statistics.AverageNonstopSentenceLength,
                Result = resolver.LeafId == "2"
            };
        }

        public ColorsStageResult ColorsStage()
        {
            ColorTable table = new ColorTable("ColorTable.txt");
            table.Load();
            Bitmap b = new Bitmap(800, 600);
            Graphics g = Graphics.FromImage(b);

            List<List<Color>> textColors = new List<List<Color>>();

            int w = 10, h = 10;
            int x, y = 2, padding = 2;
            foreach (IEnumerable<ColorWord> sent in statistics.ColorData)
            {
                x = 2;
                List<Color> sentenceColors = new List<Color>();
                foreach (ColorWord word in sent)
                {
                    String key = (word.ColorKey == "|") ? "знак." : word.ColorKey;
                    Color c = table[key];
                    sentenceColors.Add(c);
                    Rectangle rect = new Rectangle(x, y, w, h);
                    g.DrawRectangle(new Pen(Color.Black, 1), rect);
                    g.FillRectangle(new SolidBrush(c), rect);
                    x += w + padding;
                }
                y += h + padding;
                textColors.Add(sentenceColors);
            }

            return new ColorsStageResult() 
            { 
                bitmap = b,
                squares = textColors
            };
        }

        public uint[] ShinglesStage(int length = 5)
        {
            IEnumerable<Word> words = statistics.Sentences.SelectMany(s => s.Words);
            String[] stopPoses = new[] { "ПРЕДЛ", "СОЮЗ", "ЧАСТ", "" };
            words = words.Where(w => !stopPoses.Any(s => s == w.Pos));
            String[] canonicals = words.Select(w => w.Lemma.ToLower()).ToArray();
            List<uint> shingles = new List<uint>();
            for (int i = 0; i + length < canonicals.Length; i++)
            {
                Crc32 crc = new Crc32();
                String str = String.Join("", canonicals.Skip(i).Take(length));
                byte[] bytes = Encoding.Default.GetBytes(str);
                crc.ComputeHash(bytes);
                shingles.Add(crc.CrcValue);
            }
            return shingles.ToArray();
        }
    }

    public delegate StageResult StageHandler();

    public class StageResult { }

    public class IdfStageResult : StageResult
    {
        public bool Result { get; set; }
        public double Defects { get; set; }
    }

    public class StatisticsStageResult : StageResult
    {
        public double GzipRate { get; set; }
        public double Bz2Rate { get; set; }
        public Dictionary<String, double> Variances { get; set; }
        public Dictionary<String, double> Percents { get; set; }
        public String Solution { get; set; }
        public double AvgLength { get; set; }
        public double AvgLengthWithoutStop { get; set; }
        public bool Result { get; set; }
    }

    public class ColorsStageResult : StageResult
    {
        public Bitmap bitmap { get; set; }
        public List<List<Color>> squares { get; set; }
    }
}
